﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Safebrowsing
{
    /// <summary>
    /// Represents response from the redirect URL.
    /// Look here for details on redirect response format: http://code.google.com/apis/safebrowsing/developers_guide_v2.html#HTTPResponseForDataBody
    /// </summary>
    public class RedirectResponse
    {
        /// <summary>
        /// Creates redirect response from the data supplied
        /// </summary>
        /// <param name="data"></param>
        public RedirectResponse(byte[] data)
        {
            AddChunks = new List<Chunk>();
            SubChunks = new List<Chunk>();

            using (Stream stream = new MemoryStream(data) { Position = 0 })
            {
                string line = Utils.ReadLine(stream);

                while (!string.IsNullOrEmpty(line))
                {
                    if (line.StartsWith(Constants.MARK_ADDCHUNK))
                    {
                        Chunk chunk = ReadChunk(ChunkType.Add, line.Substring(Constants.MARK_ADDCHUNK.Length), stream);
                        if (chunk != null) AddChunks.Add(chunk);
                    }
                    else if (line.StartsWith(Constants.MARK_SUBCHUNK))
                    {
                        Chunk chunk = ReadChunk(ChunkType.Sub, line.Substring(Constants.MARK_SUBCHUNK.Length), stream);
                        if (chunk != null) SubChunks.Add(chunk);
                    }

                    line = Utils.ReadLine(stream);
                }
            }
        }

        private static Chunk ReadChunk(ChunkType type, string chunkHead, Stream stream)
        {
            string[] parts = chunkHead.Split(new[] {':'}, StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length != 3) return null;
            int chunkNumber = Utils.ToInt(parts[0], -1);
            int hashLength = Utils.ToInt(parts[1], -1);
            int chunkLength = Utils.ToInt(parts[2], -1);
            if (chunkNumber == -1 || hashLength == -1 || chunkLength == -1) return null;
            byte[] chunkData = Utils.Read(stream, chunkLength);
            return new Chunk(chunkNumber, type, hashLength, chunkData);
        }

        public List<Chunk> AddChunks { get; private set; }

        public List<Chunk> SubChunks { get; private set; }

        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.AppendLine("Redirect response");
            if (AddChunks.Count > 0)
            {
                sb.AppendFormat("Add chunks:");
                sb.AppendLine();
                foreach (Chunk chunk in AddChunks)
                {
                    sb.AppendLine(chunk.ToString());
                }
            }
            if (SubChunks.Count > 0)
            {
                sb.AppendFormat("Sub chunks:");
                sb.AppendLine();
                foreach (Chunk chunk in SubChunks)
                {
                    sb.AppendLine(chunk.ToString());
                }
            }

            return sb.ToString();
        }
    }
}
